package com.gxaedu.shiro.service.impl;

import com.gxaedu.shiro.dto.ResponseData;
import com.gxaedu.shiro.dto.ResultData;
import com.gxaedu.shiro.mapper.AuthMapper;
import com.gxaedu.shiro.pojo.Auth;
import com.gxaedu.shiro.pojo.Menu;
import com.gxaedu.shiro.pojo.Role;
import com.gxaedu.shiro.pojo.User;
import com.gxaedu.shiro.service.MenuService;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @author:Teacher黄
 * @date:Created at 2020/04/21
 */
@Service
@SuppressWarnings("all")
public class MenuServiceImpl implements MenuService {
    /**
     * 权限得mapper
     */
    @Autowired
    private AuthMapper authMapper;
    @Autowired
    private RedisTemplate<String,Object> jsonRedisTemplate;

    @Override
    public ResultData getMenu(HttpServletRequest request) {
        // 这个resultData里面到底应该放什么数据
        // 我们发现 菜单 是父子级得关系  parent  child
        // 先获取所有Auth中得菜单项 , 再将菜单项转换成 Menu

        /*// 1. 先判断是否是超级管理员?
        User user = (User) request.getSession().getAttribute("user");*/

        // 1. 先判断是否是超级管理员? 从redis中取获取
        // 先准备一个key, 名字怎么取?-> 通过Shiro来获取
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        String loginUserKey = "login:user:"+userName;
        User user = (User) jsonRedisTemplate.opsForValue().get(loginUserKey);
        List<Auth> menuAuth = null;
        if (isSuper(user)) {
            // 超级管理员 => 获取所有得菜单
            menuAuth = authMapper.findAllMenu();
        }else{
            // 普通管理员 => 获取session中得菜单
            menuAuth = getMenuAuth(user);
        }
        return ResponseData.success(transAuth2Menu(menuAuth));
    }


    /**
     * 判断是否是超级管理员
     * @param user
     * @return
     */
    private Boolean isSuper(User user){
        List<Role> roles = user.getRoles();
        if (roles.size() == 0) {
            // 用户如果没有角色,那么就不是超级管理员
            return false;
        }
        // 遍历判断是否是超级管理员
        for (Role role : roles) {
            if (role.getIsSuper().equals(1L)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 获取非超级管理员得菜单权限
     * @param user
     * @return
     */
    private List<Auth> getMenuAuth(User user){
        // 提前准备一个总得Auth集合
        List<Auth> menuAuth = new ArrayList<>();
        // 1. 先获取角色
        List<Role> roles = user.getRoles();
        // 2. 再从role中去获取Auth
        for (Role role : roles) {
            List<Auth> auths = role.getAuths();
            // 能不能直接添加进去? 肯不能
            // auths 里面包含了操作权限, 所以我们需要筛选
            for (Auth auth : auths) {
                if (auth.getIsMenu().equals(1L)){
                    // 是菜单权限
                    menuAuth.add(auth);
                }
            }
        }

        return menuAuth;
    }


    /**
     * 将菜单权限转换成 Menu
     * @param menuAuth
     * @return
     */
    private List<Menu> transAuth2Menu(List<Auth> menuAuth){
        List<Menu> menus = new ArrayList<>();
        // 1. 先组装父级菜单
        for (Auth auth : menuAuth) {
            if (auth.getAuthLevel().equals(1L) && auth.getAuthParentId().equals(0L)) {
                // 说明当前项是父级菜单
                menus.add(new Menu(auth.getAuthId(),auth.getAuthName()));
            }
        }
        // 2. 再组装子级菜单
        // 关键点在于如何判断 是对应父级下面得子级?
        for (Menu menu : menus) {
            // 子级得菜单集合
            List<Menu> child = new ArrayList<>();
            for (Auth auth : menuAuth) {
                if (auth.getAuthLevel().equals(2L) && menu.getMenuId().equals(auth.getAuthParentId())) {
                    // 说明是对应权限得子级
                    child.add(new Menu(auth.getAuthId(),auth.getAuthName(),auth.getAuthUrl()));
                }
            }
            menu.setChild(child);
        }
        return menus;
    }

}
